package com.siro.pm;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.siro.pm.model.Developer;
import com.siro.pm.ui.login.LoginHandler;
import com.siro.pm.utils.DatabaseOperation;
import com.siro.pm.utils.DatabasePool;
import com.siro.pm.utils.EmbededDb;
import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.HttpServletRequestListener;

public class PmApplication extends Application implements
		HttpServletRequestListener {
	private static final long serialVersionUID = -2451627338661898155L;

	private static final Logger logger = LoggerFactory
			.getLogger(PmApplication.class);

	static ThreadLocal<PmApplication> current = new ThreadLocal<PmApplication>();
	static boolean alreadyInit = false;
	private boolean invalidatedSession = false;
	private LoginHandler loginHandler = new LoginHandler();
	private MainWindow mainWindow = new MainWindow();

	public static PmApplication getDefault() {
		return current.get();
	}

	@Override
	public void init() {
		synchronized (logger) {
			if (!alreadyInit) {
				// create datasource
				initDatabase();
				alreadyInit = true;
			}
		}
		setTheme(Constants.THEME);
		setMainWindow(mainWindow);
		// mainWindow.showLoginPage();
		// setMainWindow(new LoginPage());
	}

	private void initDatabase() {
		try {
			// init parameters
			initParameters();
			// create datasource
			String db = System.getProperty("easypm.db", "H2");
			if (db.equals("H2")) {
				EmbededDb.getInstance().start();
			} else if (db.equals("MySQL")) {
				// TODO: 判断数据库是否已经初始化
				URL url = this.getClass().getClassLoader()
						.getResource(Constants.DB_INIT_SCRIPT);
				DatabaseOperation.importSqlScript(DatabasePool.getConnection(),
						url.getFile());
			}

			Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
				public void run() {
					EmbededDb.getInstance().stopDb();
				}
			}));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			System.exit(-1);
		}
	}

	private void initParameters() throws IOException {
		logger.debug("导入系统配置开始...");
		Properties props = new Properties();
		InputStream in = null;
		try {
			in = this.getClass().getClassLoader()
					.getResourceAsStream("easypm.properties");
			props.load(in);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			if (in != null)
				in.close();
		}
		Set<Object> keySet = props.keySet();
		for (Object key : keySet) {
			String k = (String) key;
			System.setProperty(k, props.getProperty(k));
		}
		logger.debug("导入系统配置成功");

	}

	@Override
	public void close() {
		removeWindow(getMainWindow());
		super.close();
	}

	public void onRequestStart(HttpServletRequest request,
			HttpServletResponse response) {
		// Set current application object as thread-local to make it easy
		// accessible
		current.set(this);

		// Authentication: check if user is found, otherwise send to login page
		Developer user = (Developer) getUser();
		if (user == null) {
			// First, try automatic login
			user = loginHandler.authenticate(request, response);
			if (user == null) {
				if (mainWindow != null && !mainWindow.isShowingLoginPage()) {
					mainWindow.showLoginPage();
				}
			} else {
				setUser(user);
			}
		}

		if (user != null) {
			if (mainWindow != null && mainWindow.isShowingLoginPage()) {
				mainWindow.showMainPage();
			}
		}

		// Callback to the login handler
		loginHandler.onRequestStart(request, response);
	}

	public void onRequestEnd(HttpServletRequest request,
			HttpServletResponse response) {
		// Clean up thread-local app
		current.remove();

		// Callback to the login handler
		loginHandler.onRequestEnd(request, response);

		if (!isRunning() && !invalidatedSession) {
			// Clear the session context, the application has been closed during
			// this request, otherwise
			// the application will be stuck on the spring-session scope and
			// will be reused on the next
			// request, which will lead to problems
			if (request.getSession(false) != null) {
				request.getSession().invalidate();
				invalidatedSession = true;
			}
		}
	}
}
